# -*- coding: utf-8 -*-
from odoo import api, fields, models
import datetime
from odoo.exceptions import AccessError, UserError, ValidationError

class InheritSaleOrder(models.Model):
    _inherit = 'sale.order'

    copy_user_id = fields.Many2one(related='user_id', string='業務員')
    copy_company_id = fields.Many2one(related='company_id', string='銷售的健身房')
    class_len = fields.Integer(compute='_compute_take_count')
    contract_sdate = fields.Date(string="合約生效日", required=False, )
    contract_edate = fields.Date(string="合約到期日", required=False, )
    Identity_type = fields.Selection(string="身份別", selection=[(u'新生', u'新生'), (u'續約生', u'續約生'), ], required=False, )
    Introducer = fields.Char(string="介紹人", required=False, )
    contract_memo = fields.Char(string="備註", required=False, )
    partner_line_id = fields.Char(related='partner_id.line_id', string='客戶LINE')
    partner_mobile = fields.Char(related='partner_id.mobile', string='客戶手機')

    invoice_total = fields.Float(string='已開發票金額', compute='compute_invoice_total', store=True)
    paid_total = fields.Float(string='已收款金額', compute='compute_invoice_total', store=True)
    unpaid_total = fields.Float(string='剩餘應收金額', compute='compute_invoice_total', store=True)

    sale_couch = fields.Many2one(comodel_name='res.users', string='配對教練')
    # 需要將 invoice_ids 設定為資料庫有的紀錄
    invoice_ids = fields.Many2many(store=True)

    def update_data(self):
        # sql = "UPDATE account_move_line SET account_id=3192 where name ='首期付款' and company_id = 6 and account_id = 3287"
        # self._cr.execute(sql)

        sql = "UPDATE account_move_line SET account_id = 3287 WHERE name = '整合10堂 換購 整合20堂' or name = '健身10堂換購健身20差價'"
        self._cr.execute(sql)

    # 還沒寫好不要拿掉註解ㄚㄚㄚㄚ
    # sale_class = fields.One2many(comodel_name='sale.class', inverse_name='order_id', string='購買課程表')

    # def compute_class_sale(self):
    #     bundle_list = []
    #     bundle = self.env['product.template'].search([('categ_id.name', '=', u'產品組合')])
    #     for line in bundle:
    #         b_gym = 0
    #         b_igs = 0
    #         b_teach = 0
    #         b_teach_10 = 0
    #         for row in line.child_line:
    #             if row.product_id.name == u'(課程内)10周營養追蹤':
    #                 b_teach_10 += row.product_qty
    #             elif row.product_id.name == u'(課程内)單次IGS諮詢':
    #                 b_igs += row.product_qty
    #             elif row.product_id.name == u'(課程内)單堂健身課':
    #                 b_gym += row.product_qty
    #             elif row.product_id.name == u'(課程内)營養師飲食指導':
    #                 b_teach += row.product_qty
    #         bundle_list.append({
    #             'template_id': line.id,
    #             'gym': b_gym,
    #             'igs': b_igs,
    #             'teach': b_teach,
    #             'teach10': b_teach_10
    #         })
    #
    #     for line in self.search([('amount_total','>',0)]):
    #         gym = 0
    #         igs = 0
    #         teach = 0
    #         teach_10 = 0
    #         for row in line.order_line:
    #             if row.product_id.name == u'(課程内)10周營養追蹤':
    #                 teach_10 += row.product_uom_qty
    #             elif row.product_id.name == u'(課程内)單次IGS諮詢':
    #                 igs += row.product_uom_qty
    #             elif row.product_id.name == u'(課程内)單堂健身課':
    #                 gym += row.product_uom_qty
    #             elif row.product_id.name == u'(課程内)營養師飲食指導':
    #                 teach += row.product_uom_qty
    #
    #         for obj in bundle_list:
    #             if obj['gym'] == gym and obj['igs'] == igs and obj['teach'] == teach and obj['teach10'] == teach_10:
    #                 if obj['template_id'] != None:
    #                     pro = self.env['product.product'].search([('product_tmpl_id', '=', obj['template_id'])])
    #                     if pro:
    #                         line.write({
    #                             'sale_class': [(0, 0, {
    #                         'product_class_id': pro.id,
    #                         'calss_amount': 1
    #                             })]
    #                         })

    def update_sale_order_and_invoice(self):
        for line in self.search([]):
            total = 0.0
            unpaid = 0.0
            uncheck_invoice = 0.0
            for row in line.invoice_ids:
                total += row.amount_total_signed
                if row.state == 'open' or row.state == 'paid':
                    unpaid += row.residual_signed
                elif row.state == 'draft':
                    uncheck_invoice += row.amount_total_signed
            line.invoice_total = total
            line.paid_total = total - unpaid - uncheck_invoice
            line.unpaid_total = unpaid + uncheck_invoice + line.amount_total - total

    @api.depends('invoice_ids.residual')
    def compute_invoice_total(self):
        for line in self:
            total = 0.0
            unpaid = 0.0
            uncheck_invoice = 0.0
            for row in line.invoice_ids:
                total += row.amount_total_signed
                if row.state == 'open' or row.state == 'paid':
                    unpaid += row.residual_signed
                elif row.state == 'draft':
                    uncheck_invoice += row.amount_total_signed
            line.invoice_total = total
            line.paid_total = total - unpaid - uncheck_invoice
            line.unpaid_total = unpaid + uncheck_invoice + line.amount_total - total
    # 計算有幾堂課
    def _compute_take_count(self):
        for partner in self:
            row = self.env['service.class'].search([('class_order_id.order_id', '=', partner.id)])
            partner.class_len = len(row)

    # 當改變自訂欄位的業務員或者公司，會同時改變其他資訊下的資料
    @api.onchange('copy_user_id','copy_company_id')
    def auto_set(self):
        self.user_id = self.copy_user_id
        self.company_id = self.copy_company_id

    # 查看從銷售訂單新增到課程清單有那些課程
    def open_class_list(self):
        action = self.env.ref('gym_service_checkin.service_class_view_action').read()[0]
        action['domain'] = [('class_order_id.order_id', '=', self.id)]
        return action

    # 取消銷售訂單時刪除課程清單
    @api.multi
    def action_cancel(self):
        res = super(InheritSaleOrder, self).action_cancel()
        if len(self.invoice_ids)>0:
            for line in self.invoice_ids:
                if line.state not in ('cancel'):
                    raise ValidationError(u'錯誤，此銷售單還有發票未手動取消')

        res_data = self.env['service.class'].search([('class_order_id.order_id','=',self.id)])
        for line in res_data:
            if line.class_checkin_times != 0:
                raise ValidationError(u'(%s)課程已有簽到資料!不能取消訂單!'% line.class_product_id.name)
        res_data.unlink(True)
        return res

    def change_class(self):
        for line in self.order_line.filtered(lambda r:r.gym_class_ids.ids == [] and r.product_id.check_in_ok is True):
            class_id = self.env['service.class'].create({
                'name': line.order_partner_id.id,
                'class_order_id': line.id,
                'class_product_id': line.product_id.id,
                'class_amount': line.product_uom_qty,
                'class_company_name': line.company_id.name,
                'class_product_price': line.price_reduce_taxexcl,
                'class_order_code': line.order_id.name
            })

    # 確認訂單後，將銷售訂單的明細寫入課程清單
    @api.multi
    def action_confirm(self):
        for row in self:
            if row.company_id.name == u'總公司':
                raise ValidationError(u'錯誤的訂單!!請確認當前銷售單的公司不是總公司!')
            for line in row.order_line:
                if line.product_id.check_in_ok is True:
                    class_id = row.env['service.class'].create({
                        'name': line.order_partner_id.id,
                        'class_order_id': line.id,
                        'class_product_id': line.product_id.id,
                        'class_amount': line.product_uom_qty,
                        'class_company_name': line.company_id.name,
                        'class_order_code': line.order_id.name,
                        # 將傳送訂單明細的不含稅小計到課程清單。
                        # 依照不含稅小計/數量來計算單價。
                        'class_amount_price': line.price_subtotal,
                        'class_product_price': line.price_subtotal / line.product_uom_qty
                    })
        res = super(InheritSaleOrder, self).action_confirm()
        return res

    def action_unlock(self):
        if self.env.user.company_id.name != u'總公司':
            raise ValidationError(u'錯誤，只有在總公司才能解鎖訂單')
        self.state = 'sale'

class SaleOrderLineInherit(models.Model):
    _inherit = 'sale.order.line'

    gym_class_ids = fields.One2many(comodel_name='service.class', inverse_name='class_order_id')
    sale_couch = fields.Many2one(related='order_id.sale_couch', store=True)

# class SaleClass(models.Model):
#     _name = 'sale.class'
#
#     order_id = fields.Many2one(comodel_name='sale.order')
#     product_class_id = fields.Many2one(comodel_name='product.product', string='套餐名稱')
#     calss_amount = fields.Integer(string='數量')

class product_template(models.Model):
    _inherit = ['product.template']

    check_in_ok = fields.Boolean(string='可簽到')


class ServiceClass(models.Model):
    _name = 'service.class'
    _rec_name = 'class_product_id'
    _description = u'課程明細檔'

    name = fields.Many2one(comodel_name='res.partner', string='客戶', ondelete='cascade', readonly=True)
    class_order_id = fields.Many2one(comodel_name='sale.order.line', string='關聯的訂單', ondelete='cascade', readonly=True)
    class_product_id = fields.Many2one(comodel_name='product.product', string='簽到產品', ondelete='cascade', readonly=True)
    class_order_code = fields.Char(string='訂單編號')
    class_amount = fields.Integer(string='購買堂數', readonly=True)
    class_checkin_times = fields.Integer(string='已簽到次數', compute='comput_times', store=True)
    class_checkin_rest = fields.Integer(string='剩餘簽到次數', compute='comput_times', store=True)
    class_checkin_list = fields.One2many(comodel_name='service.checkin.line', inverse_name='checkin_order2', string='已簽到列表')
    class_sale_user_id = fields.Many2one(related='class_order_id.salesman_id', string='業務員', store=True)
    class_company_name = fields.Char(string='公司名稱', readonly=True)
    class_couch = fields.Many2one(related='class_order_id.sale_couch', string='配對教練', store=True)

    class_checkin_price = fields.Float(string='已簽到金額', compute='comput_times', store=True)
    class_amount_price = fields.Float(string='總金額')
    class_checkin_rest_prcie = fields.Float(string='剩餘金額', compute='comput_times', store=True)
    class_product_price = fields.Float(string='單價', readonly=True)

    class_checkin_today = fields.Boolean(string='是否今日已經簽到', company_dependent=True)
    today_checkin_time = fields.Datetime(string='今日簽到時間', company_dependent=True)
    today_checkin_record = fields.Many2one(comodel_name='service.checkin.line', string='今日看板簽到明細', company_dependent=True)

    def update_rest_amount_by_time(self):
        for line in self.search([]):
            if line.class_checkin_list.ids:
                class_total = line.class_amount
                for row in line.class_checkin_list:
                    row.checkin_rest_amount = class_total
                    class_total -= row.checkin_amount

    def update_order_name(self):
        for line in self.search([]):
            name =line.class_order_id.order_id.name
            line.class_order_code = name
    @api.multi
    def name_get(self, context=None):
        result = []
        for record in self:
            name = "[%s] %s" % (record.class_order_code, record.class_product_id.name)
            result.append((record.id, name))
        return result

    @api.multi
    def unlink(self, cancel=False):
        if cancel is False:
            raise UserError("錯誤，無法從課程頁面刪除，請至銷售訂單取消該訂單")
        return super(ServiceClass, self).unlink()

    @api.multi
    def copy(self, default=None):
        if default == {}:
            raise UserError("錯誤，無法複製課程")
        return super(ServiceClass, self).copy(default)

    # 檢查簽到次數用
    @api.constrains('class_checkin_rest')
    def check_amount(self):
        for line in self:
            if line.class_checkin_rest < 0:
                raise ValidationError(u'客戶：%s的 %s 剩餘訂購次數小於簽到次數' % (line.name.name, line.class_product_id.name))

    @api.depends('class_checkin_list.checkin_amount','class_checkin_list.parent','class_product_price')
    def comput_times(self):
        for line in self:
            line.checkin_times = 0
            for row in line.class_checkin_list:
                line.class_checkin_times += row.checkin_amount
            line.class_checkin_rest = line.class_amount - line.class_checkin_times
            line.class_checkin_rest_prcie = line.class_product_price * line.class_checkin_rest
            line.class_checkin_price = line.class_product_price * line.class_checkin_times

    def update_product_price(self):
        for line in self.search([]):
            line.class_product_price = line.class_order_id.price_reduce_taxexcl

    def check_in_kanban(self):
        if self.class_checkin_rest < 1:
            raise ValidationError(u"課程已使用完畢!!")

        view = self.env.ref('gym_service_checkin.gym_checkin_couch_wizard')
        wiz = self.env['checkin.couch'].create({'checkin_class': self.id, 'checkin_couch': 1})
        return {
            'name': '簽到資料',
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'checkin.couch',
            'view_id': view.id,
            'target': 'new',
            'res_id': wiz.id,
            'context': self.env.context,
        }

    def uncheck_in_kanban(self):
        self.class_checkin_today = False
        self.today_checkin_time = None
        record = self.today_checkin_record
        # if len(record) != 1:
        #     raise ValidationError("取消簽到錯誤!!")
        for line in self.env['service.checkin.line'].search([('id', '=', record.id)]):
            line.unlink()
            break

    def day_clean_kanban(self):
        for row in self.env['res.company'].sudo().search([]):
            for line in self.with_context(force_company=row.id).search([('class_checkin_today', '=', True)]):
                line.class_checkin_today = False
                line.today_checkin_time = False
                line.today_checkin_record = False


class ServiceCheckin(models.Model):
    _name = 'service.checkin'
    _description = u'簽到主檔'
    _order = 'id desc'

    name = fields.Char(string='簽到ID')
    checkin_date = fields.Datetime(string='建表時間', default=lambda self: fields.Datetime.now(), readonly=True)
    checkin_member = fields.Many2one(comodel_name='res.users', string='執行員工', default=lambda self: self.env.user.id)
    # checkin_pack = fields.Many2one(comodel_name='product.product',string='簽到產品', domain=[('check_in_ok','=',True)])
    checkin_list = fields.One2many(comodel_name='service.checkin.line',inverse_name='parent',string='簽到明細')
    checkin_account = fields.Many2one(comodel_name='account.move', string='會計憑證')
    checkin_account_list = fields.One2many(comodel_name='account.move' ,inverse_name='class_service_id',string='會計憑證列表')
    checkin_account_len = fields.Integer(compute='_compute_account_count')
    state = fields.Selection([(1, '未產生會計傳票'), (2, '已產生')],string='Status', default=1, index=True)

    checkin_list_string = fields.Char(string='簽到明細', compute='compute_list_char', store=True)

    is_kanban_checkin = fields.Boolean(string='是否看板簽到')
    kanban_create_company = fields.Many2one(comodel_name='res.company', default=lambda self: self.env.user.company_id.id, string='簽到主檔所屬公司')
    notes = fields.Text(string='附註')


    def check_many2one_crrect(self):
        error_ids = []
        for line in self.search([]):
            for row in line.checkin_list:
                if row.checkin_order2.name.id != row.checkin_partner.id:
                    error_ids.append(row.checkin_order2.display_name)
        for line in error_ids:
            print line

    @api.depends('checkin_list')
    def compute_list_char(self):
        for line in self:
            sb = ''
            for row in line.checkin_list:
                sb += row.checkin_partner.name + ','
            line.checkin_list_string = sb

    # 計算產生的會計憑證有幾張
    def _compute_account_count(self):
        for partner in self:
            partner.checkin_account_len = len(partner.checkin_account_list)

    # 查看會計憑證用
    def open_account_list(self):
        action = self.env.ref('account.action_move_journal_line').read()[0]
        action['domain'] = [('class_service_id', '=', self.id)]
        return action

    @api.multi
    def unlink(self):
        for line in self:
            if line.state == 2:
                raise UserError("錯誤，無法刪除已產生傳票的簽到記錄")
        return super(ServiceCheckin, self).unlink()

    @api.model
    def create(self, vals):
        now_code = fields.datetime.now().strftime("%Y%m%d")
        res_id = super(ServiceCheckin, self).create(vals)
        res_id.write({
            'name': self.env.user.company_id.name + str(now_code) + str(res_id.id)
        })
        return res_id

    # 產生會計憑證用：尋找同樣會計科目的名字中，屬於某個的科目
    def compute_account_id(self, account, company):
         account_list= self.env['account.account'].search([('code', '=', account.code),('company_id','=',company.id)])
         return account_list.id

    # 產生會計憑證用：尋找是其他分錄的名字中，屬於某個公司的分錄
    def compute_journal(self, company):
        jounal_list = self.env['account.journal'].search([('company_id','=',company.id),('type','=','general'),('code','=','MISC')])
        return jounal_list.id

    # 產生會計憑證
    def checkuin_access(self):
        if self.state != 1:
            raise ValidationError(u'錯誤，會計憑證已產生')
        if self.env.user.company_id.name != u'總公司' and self.env.user.company_id.name != u'數立有限公司':
            raise ValidationError(u'錯誤，只有在總公司或(數立有限公司)才能產生會計憑證')
        account = self.env['account.move']
        # 先找出簽到明細有哪幾家公司
        company = self.env['res.company']
        for line in self.checkin_list:
            now_company = line.checkin_order2.class_order_id.company_id
            exist = False
            for company_line in company:
                if company_line == now_company:
                    exist = True
            if exist is False:
                company += now_company
        # 再將同一公司的明細通通放到res，最後在一次寫入
        for line in company:
            res = []
            account_id = None

            for row in self.checkin_list:
                list_company = row.checkin_order2.class_order_id.company_id
                if line == list_company:
                    # 檢查該公司的產品的會計科目有沒有設好
                    # if list.checkin_order2.class_order_id.product_id.get_in_account_id:
                    #     raise ValidationError(u'產品%s未設定好會計科目，在%s' % (list.checkin_order2.class_order_id.product_id.name,list_company.name))
                    # if list.checkin_order2.class_order_id.product_id.property_account_income_id:
                    #     raise ValidationError(u'產品%s未設定好會計科目，在%s' % (list.checkin_order2.class_order_id.product_id.name,list_company.name))

                    checkin_amount = row.checkin_amount
                    # 取得產品的分類的會計科目
                    credit_account = row.checkin_order2.class_order_id.product_id.categ_id.get_in_account_id

                    credit = {
                        'account_id': self.compute_account_id(credit_account, line),
                        'credit': row.checkin_order2.class_product_price * checkin_amount,
                        'name': row.checkin_order2.class_product_id.name,
                        'partner_id': row.checkin_order2.name.id
                    }
                    debit_account = row.checkin_order2.class_order_id.product_id.categ_id.property_account_income_categ_id
                    # 取得產品的分類的會計科目
                    debit = {
                            'account_id': self.compute_account_id(debit_account, line),
                            'debit': row.checkin_order2.class_product_price * checkin_amount,
                            'name': row.checkin_order2.class_product_id.name,
                            'partner_id': row.checkin_order2.name.id
                             }
                    res.append([0, 0, credit])
                    res.append([0, 0, debit])

            account_id = account.create({
                'journal_id': self.compute_journal(line),
                'class_service_id': self.id
            })
            account_id.write({
                'line_ids': res,
            })
        self.state = 2

    def rollback_state(self):
        if self.checkin_account_len != 0:
            raise ValidationError(u'錯誤，請先手動刪除已產生的%s筆會計憑證'%self.checkin_account_len)
        self.state = 1


class InheritAccountMoove(models.Model):
    _inherit = 'account.move'

    class_service_id = fields.Many2one(comodel_name='service.checkin', string='關聯的簽到主檔', ondelete='cascade')


class ServiceCheckinLine(models.Model):
    _name = 'service.checkin.line'
    _description = u'簽到明細檔'
    _rec_name = 'checkin_partner'

    name = fields.Char()
    parent = fields.Many2one(comodel_name='service.checkin', ondelete='cascade')
    checkin_partner = fields.Many2one(comodel_name='res.partner', string='簽到客戶', required=True, default=False)
    checkin_order2 = fields.Many2one(comodel_name='service.class', string='銷售訂單', required=True,
                                     domain="[('name','=', checkin_partner),('class_checkin_rest','>',0)]", ondelete='cascade')
    checkin_rest_amount = fields.Integer(string='簽到當時剩餘次數')
    checkin_amount = fields.Integer(string='簽到次數', default=1)
    checkin_member = fields.Many2one(comodel_name='res.users', string='執行員工', compute='compute_set_class', store=True)
    checkin_couch = fields.Many2one(comodel_name='res.users', string='教練', required=True)
    checkin_sale_user_id = fields.Many2one(related='checkin_order2.class_order_id.salesman_id', string='業務員', store=True)
    checkin_parent_date = fields.Datetime(default=lambda self: fields.Datetime.now(), string='簽到時間(明細)')
    notes = fields.Text(string='備註')
    checin_class_product = fields.Many2one(related='checkin_order2.class_product_id', store=True, string='簽到產品')
    # 將簽到明細寫入執行員工
    @api.depends('parent.checkin_member')
    def compute_set_class(self):
        for line in self:
            line.checkin_member = line.parent.checkin_member

    @api.onchange('checkin_order2')
    def set_rest_aamount(self):
        for line in self:
            line.checkin_rest_amount = line.checkin_order2.class_checkin_rest + line.checkin_amount

    # 塞選顯示的客戶為有購買課程的客戶列表
    @api.onchange('checkin_partner')
    def domain_partner(self):
        if self.checkin_order2 is not False:
            self.checkin_order2 = False
        partner_list = self.env['service.class'].search([])
        res = self.env['res.partner']
        for line in partner_list:
            exist = False
            for row in res:
                if row == line.name:
                    exist = True
                    break
            if exist is False and line.class_checkin_rest > 0:
                res += line.name
        return {
            'domain': {
                'checkin_partner': [('id', 'in', res.ids)],
            }}